home *** CD-ROM | disk | FTP | other *** search
- #import "UniqueKey.h"
- #import "Projects.h"
-
-
- static BOOL _Debug = YES;
-
- @implementation Projects
-
- /******************************************************************************
- * Create two instances of the UniqueKey object to grab blocks of <count> keys for
- * our use during inserts. The count is set low so you can see the SQL reserve
- * blocks of keys. Up the count to something larger for it to be of use.
- *
- * The login information (connection dictionary) in the model has been blanked out,
- * since you may elect to have the tables in some database other than PEOPLE, so we
- * elect to run a login panel. Once the login is complete we can get the
- * connection dictionary from the adaptor and use that information to allow
- * UniqueKey to login and create its separate connection for key reservation.
- *
- * Note the content views of the employee and project boxes and paste in the
- * default content.
- ******************************************************************************/
- - appDidInit:sender
- {
- EOAdaptor *eoAdaptor;
-
- dbChannel = [[(id)[employeeController dataSource] databaseChannel] retain];
- dbContext = [[dbChannel databaseContext] retain];
-
- if(_Debug) [[dbChannel adaptorChannel] setDelegate:self];
-
- projectEntity = [[(id)[projectController dataSource] entity] retain];
- employeeEntity = [[(id)[employeeController dataSource] entity] retain];
- empProjectEntity = [[(id)[projectEntity relationshipNamed:@"toEmpProjects"] destinationEntity] retain];
- empProjectDDS = [[EODatabaseDataSource alloc] initWithDatabaseChannel: dbChannel
- entityNamed: [empProjectEntity name]];
- eoAdaptor = [[[dbChannel adaptorChannel] adaptorContext] adaptor];
- if(![eoAdaptor runLoginPanelAndValidateConnectionDictionary]) [NXApp terminate:self];
- [UniqueKey setConnectionDictionary:[eoAdaptor connectionDictionary]];
-
- projectUniqueKey = [[[UniqueKey alloc] initWithEntity:projectEntity count:5] retain];
- employeeUniqueKey = [[[UniqueKey alloc] initWithEntity:employeeEntity count:5] retain];
- if(!projectUniqueKey || !employeeUniqueKey) [NXApp terminate:self];
-
- [self setFetchOrderFor:projectController with:@"ProjectName" order:EOAscendingOrder];
- [self setFetchOrderFor:addProjectsForEmployeeController with:@"ProjectName" order:EOAscendingOrder];
- [self setFetchOrderFor:employeeController with:@"LastName" order:EOAscendingOrder];
- [self setFetchOrderFor:addEmployeesOnProjectController with:@"LastName" order:EOAscendingOrder];
-
- [addProjectsForEmployeeController setSelectsFirstObjectAfterFetch:NO];
- [addEmployeesOnProjectController setSelectsFirstObjectAfterFetch:NO];
-
- inspectorWindow=[swapBox window];
- [self projectInspector:nil]; // swap in the project content view
- [[inspectorWindow center] makeKeyAndOrderFront:nil];
- return self;
- }
-
-
- /******************************************************************************
- * Set a controller's data source to fetch sorted by a given attribute name
- * and order.
- ******************************************************************************/
- - setFetchOrderFor:(EOController*)controller with:(NSString*)attributeName order:(EOOrdering)order
- {
- id dataSource = [controller dataSource];
- id attribute = [[dataSource entity] attributeNamed:attributeName];
- NSArray *orderArray;
-
- orderArray = [NSArray arrayWithObject:
- [EOAttributeOrdering attributeOrderingWithAttribute:attribute ordering:order]];
- [dataSource setFetchOrder:orderArray];
- return self;
- }
-
-
- /******************************************************************************
- * Accept the users selection for either the Employee or Project inspector. Swap
- * in the appropriate content view.
- ******************************************************************************/
- - employeeInspector:sender
- {
- [inspectorWindow disableFlushWindow];
- [swapBox setContentView:[employeeBox contentView]];
- [employeeController fetch];
- [swapBox display];
- [[inspectorWindow reenableFlushWindow] flushWindowIfNeeded];
- return self;
- }
-
- - projectInspector:sender
- {
- [inspectorWindow disableFlushWindow];
- [swapBox setContentView:[projectBox contentView]];
- [projectController fetch];
- [swapBox display];
- [[inspectorWindow reenableFlushWindow] flushWindowIfNeeded];
- return self;
- }
-
-
- /******************************************************************************
- * Utility to create an intermediate table empProject EOGenericRecord.
- ******************************************************************************/
- - createEmpProject:(NSNumber*)empId:(NSNumber*)projectId
- {
- EOGenericRecord *empProject = [empProjectDDS createObject];
-
- [empProject setObject:projectId forKey:@"ProjectId"];
- [empProject setObject:empId forKey:@"EmpId"];
- return empProject;
- }
-
-
- /******************************************************************************
- * Bring up the add employee selection panel and start a modal session. Construct
- * and 'otherEmployees' qualifier to select employees that do not already appear
- * in the EmployeesOnProject detail view.
- ******************************************************************************/
- - addEmployeesOnProject:sender
- {
- EOGenericRecord *project = [(id)[employeesOnProjectController dataSource] masterObject];
- NSNumber *projectId = [project objectForKey:@"ProjectId"];
- EOQualifier *otherEmployees;
- NSString *qualifierString;
-
- qualifierString = [NSString stringWithFormat:
- @"EmpId not in (SELECT z1.EMP_ID FROM EMPLOYEE z1, EMP_PROJECT z2 "
- @"WHERE z1.EMP_ID = z2.EMP_ID AND z2.PROJECT_ID = %@)",projectId];
-
- otherEmployees = [[[EOQualifier alloc]
- initWithEntity:employeeEntity qualifierFormat:qualifierString] autorelease];
-
- [(id)[addEmployeesOnProjectController dataSource] setQualifier:otherEmployees];
- [addEmployeesOnProjectController clearSelection];
- [addEmployeesOnProjectController fetch];
- [[addEmployeesPanel center] makeKeyAndOrderFront:nil];
- [NXApp runModalFor:addEmployeesPanel];
- [addEmployeesPanel orderOut:self];
- [projectController fetch];
- return self;
- }
-
- - addEmployeesOnProjectOK:sender
- {
- NSArray *eArray;
- NSEnumerator *eEnumerator;
- EOGenericRecord *project;
- NSNumber *projectId;
- EOGenericRecord *employee;
- EOGenericRecord *empProject;
-
- eArray = [addEmployeesOnProjectController selectedObjects];
- eEnumerator = [eArray objectEnumerator];
- project = [(id)[employeesOnProjectController dataSource] masterObject];
- projectId = [project objectForKey:@"ProjectId"];
- [dbContext beginTransaction];
- while((employee = [eEnumerator nextObject]) != nil) {
- empProject = [self createEmpProject:[employee objectForKey:@"EmpId"]:projectId];
- [dbChannel insertObject:empProject];
- }
- [dbContext commitTransaction];
- [NXApp stopModal];
- return self;
- }
-
-
- /******************************************************************************
- * Bring up the add project selection panel and start a modal session. Construct
- * and 'otherProjects' qualifier to select project that do not already appear
- * in the ProjectsForEmployee detail view. We use an imbedded select here with
- * '.' chars in the qualifier string. These names will not be converted, since they
- * contain '.' chars, so we have the ability to write qualifiers that
- * reference external names it we like.
- ******************************************************************************/
- - addProjectsForEmployee:sender
- {
- EOGenericRecord *employee = [(id)[projectsForEmployeeController dataSource] masterObject];
- NSNumber *empId = [employee objectForKey:@"EmpId"];
- EOQualifier *otherProjects;
- NSString *qualifierString;
-
- qualifierString = [NSString stringWithFormat:
- @"ProjectId not in (SELECT z1.PROJECT_ID FROM PROJECT z1, EMP_PROJECT z2 "
- @"WHERE z1.PROJECT_ID = z2.PROJECT_ID AND z2.EMP_ID = %@)",empId];
-
- otherProjects = [[[EOQualifier alloc]
- initWithEntity:projectEntity qualifierFormat:qualifierString] autorelease];
-
- [(id)[addProjectsForEmployeeController dataSource] setQualifier:otherProjects];
- [addProjectsForEmployeeController clearSelection];
- [addProjectsForEmployeeController fetch];
- [[addProjectsPanel center] makeKeyAndOrderFront:nil];
- [NXApp runModalFor:addProjectsPanel];
- [addProjectsPanel orderOut:self];
- [employeeController fetch];
- return self;
- }
-
- - addProjectsForEmployeeOK:sender
- {
- NSArray *pArray;
- NSEnumerator *pEnumerator;
- EOGenericRecord *employee;
- NSNumber *empId;
- EOGenericRecord *project;
- EOGenericRecord *empProject;
-
- pArray = [addProjectsForEmployeeController selectedObjects];
- pEnumerator = [pArray objectEnumerator];
- employee = [(id)[projectsForEmployeeController dataSource] masterObject];
- empId = [employee objectForKey:@"EmpId"];
-
- [dbContext beginTransaction];
- while((project = [pEnumerator nextObject]) != nil) {
- empProject = [self createEmpProject:empId:[project objectForKey:@"ProjectId"]];
- [dbChannel insertObject:empProject];
- }
- [dbContext commitTransaction];
- [NXApp stopModal];
- return self;
- }
-
-
- /******************************************************************************
- * Delete the intermediate table entries for the selected employee. To do this we
- * get the selected master object and ask it for the enumerator of empProject
- * objects. Since each empProject object can be asked objectForKey:@"Employee", we
- * see if that empProject object has a corresponding employee in the selected employee
- * array (eArray). We choose to use the method indexOfObjectIdenticalTo: to do the
- * check since it uses pointer equality. This works because object uniquing is
- * enabled by default.
- ******************************************************************************/
- - removeSelectedEmployeesOnProject:sender
- {
- NSArray *eArray;
- EOGenericRecord *project;
- NSEnumerator *epEnumerator;
- EOGenericRecord *empProject;
-
- eArray = [employeesOnProjectController selectedObjects];
- project = [(id)[employeesOnProjectController dataSource] masterObject];
- epEnumerator = [[project objectForKey:@"toEmpProjects"] objectEnumerator];
-
- [dbContext beginTransaction];
- while((empProject=[epEnumerator nextObject]) != nil)
- if([eArray indexOfObjectIdenticalTo:[empProject objectForKey:@"toEmployee"]]!=NSNotFound)
- [dbChannel deleteObject:empProject];
- [dbContext commitTransaction];
- [projectController fetch];
- return self;
- }
-
-
- /******************************************************************************
- * Delete the intermediate table entries for the selected project. To do this we
- * get the selected master object and ask it for the enumerator of empProject
- * objects. Since each empProject object can be asked objectForKey:@"Project", we
- * see if that empProject object has a corresponding project in the selected project
- * array (pArray). We choose to use the method indexOfObjectIdenticalTo: to do the
- * check since it uses pointer equality. This works because object uniquing is
- * enabled by default.
- ******************************************************************************/
- - removeSelectedProjectsForEmployee:sender
- {
- NSArray *pArray;
- EOGenericRecord *employee;
- NSEnumerator *epEnumerator;
- EOGenericRecord *empProject;
-
- pArray = [projectsForEmployeeController selectedObjects];
- employee = [(id)[projectsForEmployeeController dataSource] masterObject];
- epEnumerator = [[employee objectForKey:@"toEmpProjects"] objectEnumerator];
-
- [dbContext beginTransaction];
- while((empProject=[epEnumerator nextObject]) != nil)
- if([pArray indexOfObjectIdenticalTo:[empProject objectForKey:@"toProject"]]!=NSNotFound)
- [dbChannel deleteObject:empProject];
- [dbContext commitTransaction];
- [employeeController fetch];
- return self;
- }
-
-
- /******************************************************************************
- * Generate unique keys for the new object. Use the instance of UniqueKey
- * to dole out a key from its internal buffer. The UniqueKey object has its
- * own channel to the DB which it uses to allocate blocks of keys.
- ******************************************************************************/
- - (BOOL)controller:(EOController *)controller willInsertObject:object atIndex: (unsigned)newIndex
- {
- if(controller==employeeController) {
- NSArray *emptyArray1 = [[[NSArray alloc] init] autorelease];
- NSArray *emptyArray2 = [[[NSArray alloc] init] autorelease];
- NSNumber *empId = [NSNumber numberWithInt:[employeeUniqueKey nextKey]];
-
- [object setObject:empId forKey:@"EmpId"];
- [object setObject:@"<FirstName>" forKey:@"FirstName"];
- [object setObject:@"<LastName>" forKey:@"LastName"];
- [object setObject:@"<Phone>" forKey:@"Phone"];
- [object setObject:emptyArray1 forKey:@"toEmpProjects"];
- [object setObject:emptyArray2 forKey:@"toProjects"];
- return YES;
- }
- if(controller==projectController) {
- NSArray *emptyArray1 = [[[NSArray alloc] init] autorelease];
- NSArray *emptyArray2 = [[[NSArray alloc] init] autorelease];
- NSNumber *projectId = [NSNumber numberWithInt:[projectUniqueKey nextKey]];
-
- [object setObject:projectId forKey:@"ProjectId"];
- [object setObject:@"<ProjectName>" forKey:@"ProjectName"];
- [object setObject:emptyArray1 forKey:@"toEmpProjects"];
- [object setObject:emptyArray2 forKey:@"toEmployees"];
- return YES;
- }
- return NO;
- }
-
-
- /******************************************************************************
- * When a project or employee is deleted, make sure we delete the entry in the
- * empProject intermediate table. Both the project and employee entities have
- * a toEmpProjects relationship which we can use to delete the intermediate
- * table records.
- ******************************************************************************/
- - (BOOL)controller:controller willDeleteObject:object
- {
- NSArray *epArray;
- NSEnumerator *epEnumerator;
- EOGenericRecord *empProject;
-
- // The employee and project entities have a toEmpProjects
- // relationship to the intermediate table
- if(controller==projectController ||
- controller==employeeController) {
- [dbContext beginTransaction];
- epArray=[object objectForKey:@"toEmpProjects"];
- epEnumerator=[epArray objectEnumerator];
- while((empProject = [epEnumerator nextObject]) != nil)
- [dbChannel deleteObject:empProject];
- [dbContext commitTransaction];
- }
- return YES;
- }
-
-
- /******************************************************************************
- * Echo SQL when debug is enabled.
- ******************************************************************************/
- - (EODelegateResponse)adaptorChannel:channel willEvaluateExpression:(NSMutableString *)expression
- {
- NSLog(expression);
- return EODelegateApproves;
- }
-
- - (void)dealloc
- {
- [dbContext release];
- [dbChannel release];
- [projectEntity release];
- [employeeEntity release];
- [empProjectEntity release];
- [projectUniqueKey release];
- [employeeUniqueKey release];
- [super dealloc];
-
- }
-
- @end
-